home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_se / e_loop.e < prev    next >
Text File  |  2000-03-25  |  10KB  |  328 lines

  1. --          This file is part of SmallEiffel The GNU Eiffel Compiler.
  2. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  3. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr
  4. --                       http://SmallEiffel.loria.fr
  5. -- SmallEiffel is  free  software;  you can  redistribute it and/or modify it
  6. -- under the terms of the GNU General Public License as published by the Free
  7. -- Software  Foundation;  either  version  2, or (at your option)  any  later
  8. -- version. SmallEiffel is distributed in the hope that it will be useful,but
  9. -- WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  10. -- or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU General Public License
  11. -- for  more  details.  You  should  have  received a copy of the GNU General
  12. -- Public  License  along  with  SmallEiffel;  see the file COPYING.  If not,
  13. -- write to the  Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  14. -- Boston, MA 02111-1307, USA.
  15. --
  16. class E_LOOP
  17.    --
  18.    -- The Eiffel instruction : "from ... until ... loop ... end".
  19.    --
  20.  
  21. inherit INSTRUCTION;
  22.  
  23. creation make
  24.  
  25. feature
  26.  
  27.    start_position: POSITION;
  28.          -- Of letter 'f' of "from".
  29.  
  30.    initialize: COMPOUND;
  31.  
  32.    invariant_clause: LOOP_INVARIANT;
  33.  
  34.    variant_clause: LOOP_VARIANT;
  35.  
  36.    until_expression: EXPRESSION;
  37.  
  38.    loop_body: COMPOUND;
  39.  
  40. feature {NONE}
  41.  
  42.    current_type: TYPE;
  43.  
  44. feature {NONE}
  45.  
  46.    make(sp: like start_position;
  47.         i: like initialize;
  48.         ic : like invariant_clause;
  49.         vc: like variant_clause;
  50.         ue : like until_expression;
  51.         lb : like loop_body) is
  52.       require
  53.          not sp.is_unknown;
  54.          ue /= Void;
  55.       do
  56.          start_position := sp;
  57.          initialize := i;
  58.          invariant_clause := ic;
  59.          variant_clause := vc;
  60.          until_expression := ue;
  61.          loop_body := lb;
  62.       ensure
  63.          start_position = sp;
  64.          initialize = i;
  65.          invariant_clause = ic;
  66.          variant_clause = vc;
  67.          until_expression = ue;
  68.          loop_body = lb;
  69.       end;
  70.  
  71. feature
  72.  
  73.    is_pre_computable: BOOLEAN is false;
  74.  
  75.    end_mark_comment: BOOLEAN is true;
  76.  
  77. feature
  78.  
  79.    afd_check is
  80.       do
  81.          if run_control.loop_check then
  82.             if variant_clause /= Void then
  83.                variant_clause.afd_check;
  84.             end;
  85.             if invariant_clause /= Void then
  86.                invariant_clause.afd_check;
  87.             end;
  88.          end;
  89.          if initialize /= Void then
  90.             initialize.afd_check;
  91.          end;
  92.          until_expression.afd_check;
  93.          if loop_body /= Void then
  94.             loop_body.afd_check;
  95.          end;
  96.       end;
  97.  
  98.    collect_c_tmp is
  99.       do
  100.       end;
  101.  
  102.    compile_to_c is
  103.       local
  104.          need_se_tmp, loop_check, variant_flag, invariant_flag: BOOLEAN;
  105.       do
  106.          loop_check := run_control.loop_check;
  107.          if loop_check and then variant_clause /= Void then
  108.             cpp.put_string("{int c=0;int v=0;%N");
  109.             variant_flag := true;
  110.          end;
  111.          if initialize /= Void then
  112.             initialize.compile_to_c;
  113.          end;
  114.          if loop_check and then invariant_clause /= Void then
  115.             invariant_clause.compile_to_c;
  116.             invariant_flag := true;
  117.          end;
  118.          until_expression.collect_c_tmp;
  119.          need_se_tmp := cpp.se_tmp_open_declaration;
  120.          cpp.put_string("while (!(");
  121.          if run_control.no_check then
  122.             cpp.trace_boolean_expression(until_expression);
  123.          else
  124.             until_expression.compile_to_c;
  125.          end;
  126.          cpp.put_string("))%N{%N");
  127.          if variant_flag then
  128.             cpp.variant_check(variant_clause.expression);
  129.          end;
  130.          if loop_body /= Void then
  131.             loop_body.compile_to_c;
  132.          end;
  133.          if invariant_flag then
  134.             invariant_clause.compile_to_c;
  135.          end;
  136.          cpp.put_string("}%N");
  137.          if need_se_tmp then
  138.             cpp.se_tmp_close_declaration;
  139.          end;
  140.          if variant_flag then
  141.             cpp.put_string(fz_12);
  142.          end;
  143.       end;
  144.  
  145.    compile_to_jvm is
  146.       local
  147.          until_point, exit_point: INTEGER;
  148.          ca: like code_attribute;
  149.          loop_check: BOOLEAN;
  150.          counter, previous: INTEGER;
  151.       do
  152.          loop_check := run_control.loop_check;
  153.          ca := code_attribute;
  154.          if loop_check then
  155.             counter := ca.extra_local_size1;
  156.             ca.opcode_iconst_0;
  157.             ca.opcode_istore(counter);
  158.             previous := ca.extra_local_size1;
  159.             ca.opcode_iconst_0;
  160.             ca.opcode_istore(previous);
  161.          end;
  162.          if initialize /= Void then
  163.             initialize.compile_to_jvm;
  164.          end;
  165.          if loop_check then
  166.             if invariant_clause /= Void then
  167.                invariant_clause.compile_to_jvm(true);
  168.                ca.opcode_pop;
  169.             end;
  170.          end;
  171.          until_point := ca.program_counter;
  172.          exit_point := until_expression.jvm_branch_if_true;
  173.          if loop_check then
  174.             if variant_clause /= Void then
  175.                ca.opcode_iload(counter);
  176.                ca.opcode_iload(previous);
  177.                ca.runtime_check_loop_variant(variant_clause.expression);
  178.                ca.opcode_istore(previous);
  179.             end;
  180.          end;
  181.          if loop_body /= Void then
  182.             loop_body.compile_to_jvm;
  183.          end;
  184.          if loop_check then
  185.             if invariant_clause /= Void then
  186.                invariant_clause.compile_to_jvm(true);
  187.                ca.opcode_pop;
  188.             end;
  189.          end;
  190.          if loop_check then
  191.             ca.opcode_iinc(counter,1);
  192.          end;
  193.          ca.opcode_goto_backward(until_point);
  194.          ca.resolve_u2_branch(exit_point);
  195.       end;
  196.  
  197.    use_current: BOOLEAN is
  198.       local
  199.          loop_check: BOOLEAN;
  200.       do
  201.          loop_check := run_control.loop_check;
  202.          if loop_check and then variant_clause /= Void then
  203.             Result := Result or else variant_clause.use_current;
  204.          end;
  205.          if initialize /= Void then
  206.             Result := Result or else initialize.use_current;
  207.          end;
  208.          Result := Result or else until_expression.use_current;
  209.          if loop_check and then invariant_clause /= Void then
  210.             Result := Result or else invariant_clause.use_current;
  211.          end;
  212.          if loop_body /= Void then
  213.             Result := Result or else loop_body.use_current;
  214.          end;
  215.       end;
  216.  
  217.    stupid_switch(r: ARRAY[RUN_CLASS]): BOOLEAN is
  218.       do
  219.          Result := (initialize = Void or else initialize.stupid_switch(r)) and then
  220.                    until_expression.stupid_switch(r) and then
  221.                    (loop_body = Void or else loop_body.stupid_switch(r));
  222.       end;
  223.  
  224.    to_runnable(ct: TYPE): like Current is
  225.       local
  226.          ue : like until_expression;
  227.          loop_check: BOOLEAN;
  228.       do
  229.          loop_check := run_control.loop_check;
  230.          if current_type = Void then
  231.             current_type := ct;
  232.             if initialize /= Void then
  233.                initialize := initialize.to_runnable(ct);
  234.                if initialize = Void then
  235.                   error(start_position,"Bad initialisation part.");
  236.                end;
  237.             end;
  238.             if loop_check and then invariant_clause /= Void then
  239.                invariant_clause := invariant_clause.to_runnable(ct);
  240.                if invariant_clause = Void then
  241.                   error(start_position,"Bad invariant.");
  242.                end;
  243.             end;
  244.             if loop_check and then variant_clause /= Void then
  245.                variant_clause := variant_clause.to_runnable(ct);
  246.                if variant_clause = Void then
  247.                   error(start_position,"Bad variant for this loop.");
  248.                end;
  249.             end;
  250.             ue := until_expression.to_runnable(ct);
  251.             if ue /= Void then
  252.                if not ue.result_type.is_boolean then
  253.                   error(ue.start_position,
  254.                         "Expression of until must be BOOLEAN.");
  255.                   eh.add_type(ue.result_type,fz_is_not_boolean);
  256.                   eh.print_as_error;
  257.                end;
  258.                until_expression := ue;
  259.             else
  260.                error(start_position, "This loop has an invalid expression.");
  261.             end;
  262.             if loop_body /= Void then
  263.                loop_body := loop_body.to_runnable(ct);
  264.                if loop_body = Void then
  265.                   error(start_position,"Invalid loop body.");
  266.                end;
  267.             end;
  268.             if nb_errors = 0 then
  269.                Result := Current;
  270.             end;
  271.          else
  272.             !!Result.make(start_position,initialize,invariant_clause,
  273.                           variant_clause,until_expression,loop_body);
  274.             Result := Result.to_runnable(ct);
  275.          end;
  276.       end;
  277.  
  278.    pretty_print is
  279.       local
  280.          semi_colon_flag: BOOLEAN;
  281.       do
  282.          fmt.indent;
  283.          fmt.keyword(fz_from);
  284.             if initialize /= Void then
  285.                initialize.pretty_print;
  286.             end;
  287.          if invariant_clause /= Void then
  288.             invariant_clause.pretty_print;
  289.          end;
  290.          if variant_clause /= Void then
  291.             fmt.indent;
  292.             fmt.keyword(fz_variant);
  293.             fmt.level_incr;
  294.             semi_colon_flag := fmt.semi_colon_flag;
  295.             fmt.set_semi_colon_flag(false);
  296.             variant_clause.pretty_print;
  297.             fmt.set_semi_colon_flag(semi_colon_flag);
  298.             fmt.level_decr;
  299.      end;
  300.          fmt.indent;
  301.          fmt.keyword(fz_until);
  302.          fmt.level_incr;
  303.          fmt.indent;
  304.          fmt.set_semi_colon_flag(false);
  305.          until_expression.pretty_print;
  306.          fmt.level_decr;
  307.          fmt.indent;
  308.          fmt.keyword(fz_loop);
  309.          fmt.indent;
  310.          if loop_body /= Void then
  311.             loop_body.pretty_print;
  312.          end;
  313.          fmt.indent;
  314.          fmt.keyword("end;");
  315.          if fmt.print_end_loop then
  316.             fmt.put_end(fz_loop);
  317.          end;
  318.       end;
  319.  
  320. invariant
  321.  
  322.    not start_position.is_unknown;
  323.  
  324.    until_expression /= Void;
  325.  
  326. end -- E_LOOP
  327.  
  328.